﻿module Leaves.NeuroCryptography.NeuralNetworks

type NeuronInput = {
    mutable Weight : float
    InputIndex : int
}

type Neuron = {
    Inputs : list<NeuronInput>
    mutable Bias : float
    mutable Function : float -> float
}

type NeuralNetwork = {
    Layers : list<list<Neuron>>
}

let ProcessNetwork network initialInputs =
    let ProcessNeuron neuron (inputValues : list<float>) =
        let products = seq {
            for input in neuron.Inputs do
                yield input.Weight * (float)inputValues.[input.InputIndex]
        }

        let inputSum = products |> Seq.sum
        neuron.Function(inputSum) 
    
    let ProcessLayer layer (layerInputs : list<float>) =
        let layerResults = seq {
            for neuron in layer do
                yield ProcessNeuron neuron layerInputs
        }

        layerResults |> Seq.toList


    let mutable layerOutput = initialInputs
    for layer in network.Layers do
        layerOutput <- ProcessLayer layer layerOutput
        
    layerOutput

